package com.danieltoms.gcSync.contact;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import javax.microedition.pim.Contact;
import javax.microedition.pim.ContactList;
import javax.microedition.pim.PIM;
import javax.microedition.pim.PIMException;
import javax.microedition.pim.PIMItem;

import net.rim.blackberry.api.pdap.PIMListListener;

import com.danieltoms.gcSync.GcSyncConstants;
import com.danieltoms.gcSync.GcSyncStore;
import com.danieltoms.gcSync.google.GoogleDataItem;
import com.danieltoms.gcSync.google.GoogleDataStore;
import com.danieltoms.gcSync.google.GoogleTypedField;

public class ContactListListener implements PIMListListener
{

	public ContactListListener()
	{

	}

	public void itemAdded(PIMItem current)
	{
		if (GcSyncStore.instance().isContactListenerEnabled())
		{
			System.out.println("contact added");

			BBContact.flattenAddress((Contact) current);
			// verify email rule

			BBContact bc = new BBContact((Contact) current);
			System.out.println("uid: " + bc.getUID());

			GoogleDataStore store = GoogleDataStore.instance();
			GoogleDataItem si = new GoogleDataItem();
			si.setBBUID(bc.getUID());
			si.setState(GoogleDataItem.BB_ADD);
			store.addGoogleDataItem(si);

			store.commit();
		}
	}

	public void itemRemoved(PIMItem arg0)
	{
		if (GcSyncStore.instance().isContactListenerEnabled())
		{

			// TODO if address edited, warn only edits from gmail screen are synced
			System.out.println("contact removed");

			BBContact bc = new BBContact((Contact) arg0);
			System.out.println("uid: " + bc.getUID());

			GoogleDataStore store = GoogleDataStore.instance();
			GoogleDataItem si = store.getSyncItemByUID(bc.getUID());

			if (si != null)
				si.setState(GoogleDataItem.BB_DELETED);

			store.commit();
		}
	}

	public void itemUpdated(PIMItem previous, PIMItem current)
	{

		if (GcSyncStore.instance().isContactListenerEnabled())
		{

			BBContact bc = new BBContact((Contact) current);
			
			GoogleDataItem gdi = GoogleDataStore.instance().getSyncItemByUID(bc.getUID());

			// if we created a new item and are editing it before we sync it
			if (gdi != null && gdi.getState() != GoogleDataItem.BB_ADD)
			{
				current = BBContact.flattenAddress((Contact) current);
				// verify email rule

				gdi.setState(GoogleDataItem.BB_UPDATED);

				bc = new BBContact((Contact) current);
				
				processEmailUpdates(previous, bc, gdi);

				GoogleDataStore.instance().commit();
			}
		}
	}

	private void processEmailUpdates(PIMItem previous, BBContact current, GoogleDataItem gdi)
	{
		// sync emails updates from the PIM to our GoogleDataItem

		BBContact prev = new BBContact((Contact) previous);
		// System.out.println("current email count: " +
		// current.getEmailCount());
		// System.out.println("prev email count: " + prev.getEmailCount());

		// short circuit if we don't have any emails
		if (prev.getEmailCount() == 0 && current.getEmailCount() == 0)
			return;

		Vector googleEmails = gdi.getEmails();

		// we may not have any emails in our gdi
		if (googleEmails == null)
		{
			googleEmails = new Vector();
			gdi.setEmails(googleEmails);
		}

		GoogleTypedField gtf = null;
		Hashtable types = new Hashtable();

		// the next loop will remove the top elements from the gdi store, and
		// save their type
		// in preparation for readding them based on the current edit
		int i = 0;
		int size = googleEmails.size();

		while (i < BBContact.getMaxEmails())
		{
			// save the type so any edits don't clear change it
			String type = GcSyncConstants.HOME_TYPE;

			// if its the primary email, set type to null
			if (i == 0)
				type = null;

			// only remove if there is an entry in the gdi
			if (i < size)
			{
				// save type
				gtf = (GoogleTypedField) googleEmails.elementAt(0);
				type = gtf.getType();

				// remove from top
				googleEmails.removeElementAt(0);

			}

			// type will be null for the primary, don't put or boom
			if (type != null)
				types.put(new Integer(i), type);

			i++;
		}

		// now push in the current bb emails and fix the type

		int count = current.getEmailCount();
		// System.out.println(" count: " + current.getEmailCount());
		count--;

		// this should push in the remaining or changed emails in order from the
		// bb contact
		// into the gdi store, which we previously cleared the top of.
		while (count > -1)
		{
			Vector bbEmails = current.getEmails();
			String email = (String) bbEmails.elementAt(count);
			gtf = new GoogleTypedField(email, (String) types.get(new Integer(count)));
			// log("inserted: " + gtf.getValue());
			googleEmails.insertElementAt(gtf, 0);
			count--;
		}

		// now make sure we have filled the bb contact, in case of a delete, we
		// push in the next ones from the gdi store
		try
		{
			// we need a new copy of the PIM contact to update it, or we'll get
			// an exception
			ContactList list = (ContactList) PIM.getInstance().openPIMList(PIM.CONTACT_LIST, PIM.READ_WRITE);

			Enumeration e = list.items(current.getContact());


			BBContact update = new BBContact((Contact) e.nextElement());

			i = 0;
			update.removeEmails();
			size = googleEmails.size();

			// refill the PIM contact from the gdi
			while ((i < BBContact.getMaxEmails()) && (i < size))
			{
				gtf = (GoogleTypedField) googleEmails.elementAt(i);
				update.addEmail(gtf.getValue());
				i++;
			}

			// we need to run off this listener before we update, else we'll
			// recurse endlessly
			GcSyncStore.instance().setContactListenerEnabled(false);

			update.commit();

			GcSyncStore.instance().setContactListenerEnabled(true);
		}
		catch (PIMException e1)
		{
			// TODO Auto-generated catch block
			e1.printStackTrace();
			System.out.println("PIMException: " + e1.getMessage());
		}

	}

	private void log(String string)
	{
		System.out.println(string);
	}

}
